package net.apexcns.core.web.util;


import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.apexcns.core.BaseVO;
import net.apexcns.core.config.ConfigEnv;
import net.apexcns.core.util.StringUtil;
import net.apexcns.core.web.file.CmmFileItem;
import net.apexcns.core.web.file.MultipartRequestWrapper;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;



@SuppressWarnings("unchecked")
public class ServletUtil {
	private static Logger logger = Logger.getLogger(ServletUtil.class);
	private static ConfigEnv configEnv = ConfigEnv.getConfig(ConfigEnv.class);
	public static final String SSN_NAME_PREFIX = "ssn";	// 세션필드명 prefix

	@SuppressWarnings("rawtypes")
	public static Map getSessionMap(HttpServletRequest req) {
		HttpSession ssn = req.getSession();
		Map ssnMap = new TreeMap();
		if(ssn==null) return ssnMap;
		Enumeration ssnNames = ssn.getAttributeNames();
		do {
			if (ssnNames == null || !ssnNames.hasMoreElements())
				break;
			String ssnName = (String) ssnNames.nextElement();
			Object value = ssn.getAttribute(ssnName);
//			logger.debug("ssnName=" + ssnName + ", value=" + value);
			ssnMap.put(ssnName, value);
		} while (true);
		return ssnMap;
	}

	@SuppressWarnings("rawtypes")
	public static Map getRequestMap(HttpServletRequest req) {
		Enumeration paramNames = req.getParameterNames();
		Map requestMap = new TreeMap();
		do {
			if (paramNames == null || !paramNames.hasMoreElements())
				break;
			String paramName = (String) paramNames.nextElement();
			String values[] = req.getParameterValues(paramName);
			if(values==null || values.length==0) continue;
			if(paramName.startsWith(SSN_NAME_PREFIX)) continue;
			requestMap.put(paramName, values);
		} while (true);
		return requestMap;
	}


	@SuppressWarnings("rawtypes")
	private static void populateRequest(Object bean, HttpServletRequest req) {
		Enumeration paramNames = req.getParameterNames();
		Map requestMap = new TreeMap();
		do {
			if (paramNames == null || !paramNames.hasMoreElements())
				break;
			String paramName = (String) paramNames.nextElement();
			String values[] = req.getParameterValues(paramName);
			if(values==null || values.length==0) continue;
			if(paramName.startsWith(SSN_NAME_PREFIX)) continue;
			try {
				if(PropertyUtils.getPropertyDescriptor(bean, paramName).getPropertyType().isArray()) {
					requestMap.put(paramName, values);
				} else {
					requestMap.put(paramName, values[0]);
				}
			} catch (Exception e) {
				//logger.warn(e.getMessage());
			}
		} while (true);
		try {
			BeanUtils.populate(bean, requestMap);
		} catch (Exception e) {
			logger.warn(e.getMessage());
		}
	}

	@SuppressWarnings("rawtypes")
	private static void populateMultipartRequest(Object bean, HttpServletRequest req) {
		if(!(req instanceof MultipartRequestWrapper)) return;
		Map items = ((MultipartRequestWrapper) req).getFileItems();
		Iterator it = items.keySet().iterator();
		Map requestMap = new TreeMap();
		while(it.hasNext()) {
			String paramName = (String) it.next();
			CmmFileItem values[] = (CmmFileItem[]) items.get(paramName);
			if(values==null || values.length==0) continue;
			if(paramName.startsWith(SSN_NAME_PREFIX)) continue;
			try {
				if(PropertyUtils.getPropertyDescriptor(bean, paramName).getPropertyType().isArray()) {
					requestMap.put(paramName, values);
				} else {
					requestMap.put(paramName, values[0]);
				}
			} catch (Exception e) {
				logger.warn(e.getMessage());
			}
		}
		try {
			BeanUtils.populate(bean, requestMap);
		} catch (Exception e) {
			logger.warn(e.getMessage());
		}
	}

	/** request.sendRedirect 시 url 인코딩용 함수 */
	public static String getRedirectUrl(String url) throws Exception {
		return getRedirectUrl(url, null);
	}

	/** request.sendRedirect 시 url 인코딩용 함수 */
	public static String getRedirectUrl(String url, String[][] param_pairs) throws Exception {
		if(param_pairs!=null) { 
			if(url.indexOf('?')==-1) url += "?";
			for(int i=0; i<param_pairs.length; i++) {
				url += "&" + param_pairs[i][0] + "=" + URLEncoder.encode(StringUtil.nvl(param_pairs[i][1]), "UTF-8");
			}
		}
		return url;
	}

	@SuppressWarnings("rawtypes")
	public static void setRequestInfo(HttpServletRequest req, Object obj, Map requestMap) {
		try {
			BeanUtils.populate(obj, getSessionMap(req));
			populateRequest(obj, req);
			populateMultipartRequest(obj, req);
			if(obj instanceof BaseVO) {
				BaseVO vo = (BaseVO) obj;
		       	vo.setRemoteIp(req.getRemoteAddr());
		    	if(vo.getPageNumber()==0) vo.setPageNumber(1);
		    	if(vo.getPageSize()==0)	vo.setPageSize(configEnv.getPageSize());
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	public static void setRequestInfo(HttpServletRequest req, Object obj) {
		setRequestInfo(req, obj, null);
	}

//	public static void setRequestInfo(HttpServletRequest req, BaseVO vo, Map requestMap) throws Exception {
//		try {
//			setRequestInfo(req, (Object) vo, requestMap);
//	       	vo.setRemoteIp(req.getRemoteAddr());
//	    	if(vo.getPageNumber()==0) vo.setPageNumber(1);
//	    	if(vo.getPageSize()==0)	vo.setPageSize(configEnv.getPageSize());
//		} catch(Exception e) {
//			throw e;
//		}
//    }
//
//	public static void setRequestInfo(HttpServletRequest req, BaseVO vo) throws Exception {
//		try {
//			setRequestInfo(req, vo, null);
//		} catch(Exception e) {
//			throw e;
//		}
//    }

    public static void printHtml(HttpServletResponse res, String html) {
		try {
			res.setContentType("text/html;charset=utf-8");
			PrintWriter out = res.getWriter();
			out.println(html);
			out.close();
		} catch (IOException io) {
			logger.error(io.getMessage(), io);
		}
	}
    
    public static boolean isMultipartContent(HttpServletRequest request) {
    	if(!"post".equalsIgnoreCase(request.getMethod())) return false;
    	if(request.getContentType() == null) return false;
    	return request.getContentType().startsWith("multipart/");
    }
}
